#include <iostream>
#include <cstring>  // For memset
#include <chrono>   // For timing
#include "test.pb.h"  // Protobuf 生成的头文件

const size_t BUFFER_SIZE = 4096; // 固定大小的缓冲区
const size_t KEY_SIZE = 16;      // 密钥大小

// 异或加密函数
void stepwiseEncrypt(const uint8_t* plaintext, size_t plaintext_size, const uint8_t* key, uint8_t* ciphertext) {
    uint8_t current_key[KEY_SIZE];
    std::memcpy(current_key, key, KEY_SIZE); // 初始化当前密钥

    size_t block_size = KEY_SIZE; // 假设每块数据为16字节

    for (size_t i = 0; i < plaintext_size; i += block_size) {
        size_t chunk_size = std::min(block_size, plaintext_size - i);

        // 对数据块进行加密
        for (size_t j = 0; j < chunk_size; ++j) {
            ciphertext[i + j] = plaintext[i + j] ^ current_key[j % KEY_SIZE];
        }

        // 用异或的结果更新密钥
        std::memcpy(current_key, ciphertext + i, block_size);
    }
}

// 异或解密函数
void stepwiseDecrypt(const uint8_t* ciphertext, size_t ciphertext_size, const uint8_t* key, uint8_t* plaintext) {
    uint8_t current_key[KEY_SIZE];

    std::memcpy(current_key, key, KEY_SIZE); // 初始化当前密钥

    size_t block_size = KEY_SIZE; // 假设每块数据为16字节

    for (size_t i = 0; i < ciphertext_size; i += block_size) {
        size_t chunk_size = std::min(block_size, ciphertext_size - i);

        // 对数据块进行解密
        for (size_t j = 0; j < chunk_size; ++j) {
            plaintext[i + j] = ciphertext[i + j] ^ current_key[j % KEY_SIZE];
        }

        // 当前密文段作为下一段密钥
        std::memcpy(current_key, ciphertext + i, chunk_size);
    }
}


int main() {
    // 创建 Protobuf 消息
    TestEncrypt message;
    message.set_content("加密解密成功");

    // 计算序列化后的消息大小
    int message_size = message.ByteSizeLong();

    // 检查消息是否适合固定大小的缓冲区
    if (message_size > BUFFER_SIZE) {
        std::cerr << "Message size exceeds buffer size" << std::endl;
        return -1;
    }

    // 使用固定大小的缓冲区和密钥数组
    uint8_t buf[BUFFER_SIZE] = {0};
    uint8_t ciphertext[BUFFER_SIZE] = {0};
    uint8_t decrypted[BUFFER_SIZE] = {0};
    const uint8_t key[KEY_SIZE] = {0x1F, 0x2E, 0x3D, 0x4C, 0x5B, 0x6A, 0x7F, 0x8E, 0x9D, 0xAC, 0xBB, 0xCA, 0xD9, 0xE8, 0xF7, 0x00};

    // 序列化消息到数组
    if (!message.SerializeToArray(buf, BUFFER_SIZE)) {
        std::cerr << "Failed to serialize Protobuf message" << std::endl;
        return -1;
    }

    // 计算1000万次加密耗时
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 10000000; i++) {
        stepwiseEncrypt(buf, message_size, key, ciphertext);
    }
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "加密 1000万次 耗时: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;

    // 计算1000万次解密耗时
    start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 10000000; i++) {
        stepwiseDecrypt(ciphertext, message_size, key, decrypted);
    }
    end = std::chrono::high_resolution_clock::now();
    std::cout << "解密 1000万次 耗时: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;

    // 反序列化解密后的数据
    TestEncrypt decryptedMessage;
    if (!decryptedMessage.ParseFromArray(decrypted, message_size)) {
        std::cerr << "Failed to parse Protobuf message" << std::endl;
        return -1;
    }

    // 打印解密后的内容
    std::cout << "解密出来的消息内容是: " << decryptedMessage.content() << std::endl;

    return 0;
}
